using System;
using System.Net;
using Jurassic.Library;
using Kiwi.Node.Modules.Builtin;

namespace Kiwi.Node.Modules.Http
{
    public class HttpServer: EventEmitter
    {
        public HttpListener Listener { get; private set; }
        public HttpServer(IApplication application): base(application)
        {
            Application.Events.Shutdown += () =>
                                        {
                                            if (Listener != null)
                                            {
                                                Listener.Stop();
                                            }
                                        };
        }

        [JSFunction(Name = "listen")]
        public HttpServer Listen(int port, string host)
        {
            var uriBuilder = new UriBuilder(){Host = host, Port = port};

            var isStarted = true;
            if (Listener == null)
            {
                Listener = new HttpListener();
                isStarted = false;
            }

            Listener.Prefixes.Add(uriBuilder.ToString());
            if (!isStarted)
            {
                Listener.Start();
                BeginGetContext(Listener);
                Application.Events.RegisterEventEmitter(this);
            }
            return this;
        }

        private void BeginGetContext(HttpListener listener)
        {
            listener.BeginGetContext(ar =>
                                         {
                                             try
                                             {
                                                 var result = listener.EndGetContext(ar);
                                                 if ((result != null) && (result.Request != null) &&
                                                     (result.Response != null))
                                                 {
                                                     var request = new HttpRequest(Application, result.Request);
                                                     var response = new HttpResponse(Application, result.Response);
                                                     Application.Events.Enque(() =>
                                                                                  {
                                                                                      HandleRequest(request, response);
                                                                                      BeginGetContext(listener);
                                                                                  });
                                                 }
                                             }
                                             catch (HttpListenerException e)
                                             {
                                                 //Console.Out.WriteLine(e.Message);
                                             }
                                         }, null);
        }

        private void HandleRequest(HttpRequest request, HttpResponse response)
        {
            try
            {
                InternalEmit("request", request, response);
            }
            finally {
                response.Close();
                InternalEmit("close");
            }
        }
    }
}